package cn.lg.soar.core.util;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 校验工具
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class ValidationUtils {

	protected static final ValidatorFactory VF = Validation.buildDefaultValidatorFactory();

	/**
	 * 校验单个对象
	 * @param data
	 * @return
	 * @param <T>
	 */
	public static <T>Set<ConstraintViolation<T>> validate(T data, Class<?>... groups) {
		Validator validator = VF.getValidator();
		return validator.validate(data, groups);
	}

	/**
	 * 校验单个对象
	 * @param data
	 * @return
	 * @param <T>
	 */
	public static <T, R>Set<R> validate(T data, Function<ConstraintViolation<? super T>, ? extends R> mapper) {
		return validate(data).stream().map(mapper).collect(Collectors.toSet());
	}

	/**
	 * 校验单个对象返回异常信息集合
	 * @param data
	 * @return
	 * @param <T>
	 */
	public static <T>Set<String> validateToMsg(T data, Class<?>... groups) {
		return validate(data, groups).stream().map(ConstraintViolation::getMessage).collect(Collectors.toSet());
	}

	/**
	 * 批量校验
	 * @param data
	 * @return
	 * @param <T>
	 */
	public static <T>List<Set<ConstraintViolation<T>>> validate(Collection<T> data, Class<?>... groups) {
		Validator validator = VF.getValidator();
		return data.stream().map(x -> validator.validate(x, groups)).collect(Collectors.toList());
	}

	/**
	 * 批量校验
	 * @param data
	 * @param mapper
	 * @return
	 * @param <T>
	 * @param <R>
	 */
	public static <T, R>List<? extends Set<? extends R>> validate(Collection<T> data, Function<ConstraintViolation<? super T>, ? extends R> mapper) {
		return validate(data)
				.stream()
				.map(x -> x.stream().map(mapper).collect(Collectors.toSet()))
				.collect(Collectors.toList());
	}

	/**
	 * 批量校验返回异常信息集合
	 * @param data
	 * @return
	 * @param <T>
	 */
	public static <T>List<Set<String>> validateToMsg(Collection<T> data, Class<?>... groups) {
		return validate(data, groups)
				.stream()
				.map(x -> x.stream().map(ConstraintViolation::getMessage).collect(Collectors.toSet()))
				.collect(Collectors.toList());
	}

}
